package com.hemerasolutions.v2trainer.util;

import java.io.Serializable;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.KeySpec;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.faces.context.FacesContext;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

@SuppressWarnings("restriction")
public class Utility implements Serializable {

	private static final long serialVersionUID = 1L;
	private static final Random random = new Random(); 
	private static SecretKey skey;
	private static KeySpec ks;
	private static PBEParameterSpec ps;
	private static BASE64Encoder enc = new BASE64Encoder();
	private static BASE64Decoder dec = new BASE64Decoder();
	private static final String algorithm = "PBEWithMD5AndDES";
	private static Calendar cal = Calendar.getInstance();

	
	static {
		try {
			SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
			ps = new PBEParameterSpec(new byte[] { 3, 1, 4, 1, 5, 9, 2, 6 }, 20);
			ks = new PBEKeySpec(
					"05Bc5hswRWpwp1sew+MSoHcj28rQ0MK8".toCharArray());
			skey = skf.generateSecret(ks);
		} catch (java.security.NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		} catch (java.security.spec.InvalidKeySpecException ex) {
			ex.printStackTrace();
		}
	}



	public static final String encrypt(String text) {

		if(text == null){
			return null;
		}
		
		try {
			final Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, skey, ps);
			return enc.encode(cipher.doFinal(text.getBytes()));

		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch ( NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch ( NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		}catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}


	public static final String decrypt(String text) {

		if(text == null){
			return null;
		}
		
		try {

			final Cipher cipher = Cipher.getInstance(algorithm);
			cipher.init(Cipher.DECRYPT_MODE, skey, ps);
			String ret = null;
			try {
				ret = new String(cipher.doFinal(dec.decodeBuffer(text)));
			} catch (Exception ex) {
				ex.printStackTrace();
			}
			return ret;
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch ( NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch ( NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		}
		return null;
	}

	
	
	
	public static String getText(String label){

		try{
			FacesContext fc = FacesContext.getCurrentInstance();
	        ResourceBundle rb = ResourceBundle.getBundle("com.hemerasolutions.v2trainer.util.messages", fc.getViewRoot().getLocale());
	        return rb.getString(label);
		}catch(Exception ex){
			System.out.println("Text not found: " + label);
			return label;
		}

	}
	
	public static String getParameter(String label){
        ResourceBundle rb = ResourceBundle.getBundle("com.hemerasolutions.v2trainer.util.parametros");
        return rb.getString(label);
	}

	
    //[0 - 9] =  0-9
    //[A - Z] = 10-35
    //[a - z] = 36-61
    private static char toChar(int index) {
        if (index < 10)
            return (char)(index + 48); //os chars 48 a 57 representam [0 - 9]
        else if (index < 36)
            return (char)(index + 55); //os chars 65 a 90 representam [A - Z]
        else
            return (char)(index + 61); //os chars 97 a 122 representam [a - z]
    }

    //char randomico entre [0 - 9], [A - Z] e [a - z]
    public static char randomChar() {
        return toChar(random.nextInt(62));
    }

    //String randomica de tamanho length, contendo apenas caracters alfanumericos
    public static String randomString(int length) {
        return new String(randomCharArray(length));
    }

    //sequencia de caracters randomicos de tamanho length, contendo apenas alfanumericos
    public static char[] randomCharArray(int length) {
        if (length < 0)
            throw new IllegalArgumentException("O tamanho da string não pode ser negativo");
        if (length == 0)
            return new char[0];
        
        char[] charSequence = new char[length];
        for (int i = 0; i<length; i++)
            charSequence[i] = randomChar();
        return charSequence;
    }

    //sequencia de caracters randomicos de tamanho entre minLength e maxLength, contendo apenas carcters alfanumericos
    public static String randomString(int minLength, int maxLength) {
        if (minLength != 0 || maxLength < 0)
            throw new IllegalArgumentException("O tamanho da string não pode ser negativo");
        if (minLength > maxLength)
            throw new IllegalArgumentException("O tamanho maximo da String não pode ser menor que o minimo");

        if (minLength == maxLength)
            return randomString(maxLength);
        int size = minLength + random.nextInt(maxLength-minLength+1);
        return randomString(size);
    }
    
	
	public static Date endDayDateHour(Date dt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		
		return cal.getTime();
	}

	public static Date begDayDateHour(Date dt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		cal.set(Calendar.HOUR_OF_DAY, 00);
		cal.set(Calendar.MINUTE, 00);
		cal.set(Calendar.SECOND, 00);
		
		return cal.getTime();
	}
	
	
    public static double dateToDouble(Date date){
    	if(date != null){
        	cal.setTime(date);
        	return (double) cal.getTimeInMillis();
    	}else{
    		return 0;
    	}
    }
    
    public static long dateToLong(Date date){
    	if(date != null){
        	cal.setTime(date);
        	return cal.getTimeInMillis();
    	}else{
    		return 0;
    	}
    }
    

    public static Date longToDate(long value){
		cal.setTimeZone(TimeZone.getTimeZone("Etc/GMT0"));
		cal.setTimeInMillis(value);
		return cal.getTime();
    }
    
    public static Date doubleToDate(double value){
		cal.setTimeZone(TimeZone.getTimeZone("Etc/GMT0"));
		cal.setTimeInMillis((long)value);
		return cal.getTime();
    }
    
    public static String timeToString(Date date){
    	String timeString = "";
    	
    	if(date != null && date.getTime() > 0){
    		
    		cal.setTimeZone(TimeZone.getTimeZone("Etc/GMT0"));
    		cal.setTime(date);
			
			long hours  = TimeUnit.MILLISECONDS.toHours(cal.getTimeInMillis());
	        long minute = TimeUnit.MILLISECONDS.toMinutes(cal.getTimeInMillis()) - hours * 60 ;
	        long second = TimeUnit.MILLISECONDS.toSeconds(cal.getTimeInMillis()) - minute * 60 - (hours * 60 * 60);
			

			if(hours >= 2){
				timeString = (timeString == ""? timeString :  timeString + " e ") + hours + " " +  Utility.getText("Hours") + " " ;
			}else if(hours == 1){
				timeString = (timeString == ""? timeString :  timeString + " e ") + hours + " " +  Utility.getText("Hour") + " " ;
			}

			if(minute >= 2){
				timeString = (timeString == ""? timeString :  timeString + " e ") + minute + " " +  Utility.getText("Minutes") + " " ;
			}else if(minute == 1){
				timeString = (timeString == ""? timeString :  timeString + " e ") + minute + " " +  Utility.getText("Minute") + " " ;
			}
			
			if(second >= 2){
				timeString = (timeString == ""? timeString :  timeString + " e ") + second + " " +  Utility.getText("Seconds") + " " ;
			}else if(second == 1){
				timeString = (timeString == ""? timeString :  timeString + " e ") + second + " " +  Utility.getText("Second") + " " ;
			}
		}
    	
    	return timeString;
    }


    public static Date getRoundedDate(){
    	return new java.util.Date(((new Date()).getTime()/1000)*1000);
    }
    
}

